﻿/**
* App类，负责管理模块、事件通知、View管理
*/

define(function (require, exports, module) {
    var FXREADER = require('./FXReader.js');
    require("./Cavans/uupaa-color.mini.js");
    require("./Cavans/uupaa-excanvas.js");
    var Config = require('./Config.js');
    var CPDF_Rect = require('./Math/Rect.js');
    var CPDF_Point = require('./Math/Point.js');
    var CMap = require('./Math/JSMap.js');
    require("./CommonDialog.js");
    var CMainFrame = require('./PDFView/MainFrame');
    var CImgPageViewRender = require('./PDFView/ImgPageViewRender');
    var IReader_InstanceEventHandler = require('./Event/IReaderInstanceEventHandler');
    var IReader_PageEventHandler = require('./Event/IPageEventHandler');
    var IReader_DocViewEventHandler = require('./Event/IDocViewEventHandler');
    var IReader_MainFrmEventHandler = require('./Event/IMainFrmEventHandler');
    var IReader_MousePtHandler = require('./Event/IMousePtHander');
    var IReader_ToolHandler = require('./Event/IReaderToolHandler');
    var CReader_HandToolHandler = require('./Event/HandToolHandler');
    var CBaseCommand = require('./BaseCommand');
    var CCommandUI = require('./CommandUI');
    var CMenuItem = require('./MenuItem');
    var PDFDocView = require('./PDFView/PDFDocView.js');
    var LayoutInfo = require('./PDFView/LayoutInfo');
    var Languages = require("./Lang.js");
    var ProgressBar = require("./ProgressBar");
    require("./PDFData/Text/TextManager");
    /**
     * @name FXREADER.AppState
     * @namespace  
	 * @description enumeration of App state.
     */
    FXREADER.AppState = {
    	/**
    	  * @description The App have been start to initilize.
    	  * @type {Number}
    	  * @constant
    	*/
        STATE_START: 0,
        /**
         * @description Document information has been getted from server.
         * @type {Number}
         * @constant
         */
        STATE_DOC_GETED: 1
    };
    
    //从服务端获取数据时的错误代码
    FXREADER.ConversionState = {
        Success: 0,
        Initialize: 1,
        InProgress: 2,
        ServiceBusy: 3,
        ConversionError: 4,
        UnknownError: 5
    };
    

    FXREADER.PDFError = 
    {
    	/**
        * unknown error.
        */
    	ERROR_UNKNOWN : -1,
    	/**
    	 * success
    	 */
    	ERROR_SUCCESS : 0,
    	/**
    	* Parse PDF file failed
    	 */
    	ERROR_PDFPARSE_FILE : 1,

    	/**
    	 * Format error
    	*/
    	ERROR_PDFPARSE_FORMAT : 2,
    	/**
    	 * PDF password error
    	*/
    	ERROR_PDFPARSE_PASSWORD : 3, 
    	/**
    	* Unsupported PDF security handler
    	*/
    	ERROR_PDFPARSE_HANDLER : 4,
    	/**
    	 * Unsupported PDF certificate
    	*/
    	ERROR_PDFPARSE_CERT : 5,
    	/**
    	 * Com error
    	*/
    	ERROR_COM_CALL : 6,
    	/**
    	 * exception 
    	 */
    	ERROR_EXCEPTION : 7, 
    	/**
    	* Get Pages info error
    	*/
    	ERROR_MANIFEST_GET_ERROR : 8,
    	/**
    	* Write data to file failed.
    	*/
    	ERROR_FILE_WRITE_ERROR : 9, 
    	/**
    	* Create images failed.
    	*/
    	ERROR_CREATE_IMAGE_ERROR : 10,
    	/**
    	* Get text information failed.
    	*/
    	ERROR_CREATE_TEXT_ERROR : 11, 
    	/**
    	* Get text information failed.
    	*/
    	ERROR_CREATE_PATH_ERROR : 12,
    		
    	/**
    	 * Page count exceed maximum value.
    	*/
    	ERROR_PDFPARSE_PAGE_COUNT_EXCEED : 13,
    	/**
    	 * load form information error.
    	*/
    	ERROR_CREAT_FORM_INFO_ERROR : 14	
    };
    
   
    FXREADER.PER_PRINT_LIMITED = 0x0008;

    /**
     * App Class.
     * @class App Class，all operations are invoked through an instance of this class.
     * @constructor
     * @param {String} fileID File ID.
     * @param {String} fileName File Name.
     * @param {String} mainFrameID ID of the mainframe element of the viewer.
     * @param {String} leftPanelID ID of the navigation panel.
     * @param {String} topPanelID ID of the top panel.
     * @return {FXREADER.CReaderApp} an App instance. 
     */
    FXREADER.CReaderApp = function (fileID, fileName, mainFrameID, leftPanelID, topPanelID,bottomPanelID,documentLoader,pPageViewRender) {
        var _pMainView = null,
             _FileID = fileID,
             _FileName = fileName,
             _pPDFDoc = null,
             _MainFrameID = mainFrameID,
             _LeftPanelID = leftPanelID,
             _TopPanelID = topPanelID,
             _BottomPanelID = bottomPanelID,
             _AppState = FXREADER.AppState.STATE_START,
        //页面图片的url格式,如 "GetPageImg.ashx?fileid=docs/dc7fef27-c0f2-4391-930b-fb0c925be30b/&page={page}&zoom={zoom}";
             _ImgUrlPattern = '',
             _pPageViewRender = pPageViewRender,
        //插件列表,存储格式为    PluginName: Plugin;
             _PluginListMap = {},
        //实例化事件处理列表
             _pInstanceEventHandlerList = [],
        //页面事件处理列表;
        _pPageEventHandlerList = [],
        //DocView事件处理列表
             _pDocViewEventHandlerList = [],
        //MousePt事件处理列表
             _pMousePtHandlerList = [],
        //工具列表,存储格式为    ToolName: Tool;
             _pToolHandlerMap = {},
        //MainFrm 事件处理列表;
             _pMainFrmEventHandlerList = [],
        //当前工具;
             _pCurToolHandler = null,
        //命令列表;
             _CommandList = {},
        //命令UI列表;
             _CommandUIList = {},
             _MenuItemList = {},
        //是否能够下载pdf源文件;
             _CanDownloadPDF = false,
        //文档权限
             _DocPemission = 0,
        //是否第一次解析文件;
             _bFirstTimeParse = true,
             _LanguageName = Config.language,
             _Language = null,
             _ToolBarCookieName = "fxreader_cookie_plugins",
        //是否处于调试状态;
             _bDebugMode = false,
        //已经加载完成步骤数量;
             _nStepLoadCnt = 0,
             _textManager = null,
             _self = this,
        //传入的文件类型（1：bin文件）
             _bFitWidth = false,
             _documentLoader = documentLoader;
        
        //获取语言文件
        _GetLanguage();
        
        
        this.LoadDocument = function(){
			//调用IDocumentLoader接口的AysncLoadDocument函数
			_documentLoader.AysncLoadDocument(_InitApp);

		};
		
		// 返回MainFrame对象，代表整个reader区域
		this.GetMainFrame = function(){
			return _pMainView;
		};

		//返回IPDFDocument接口
		this.GetPDFDocument = function(){
			return _pPDFDoc;
		};

        function _InitApp(pdfDoc,status){
			if(status == "success"){
				FXREADER.CloseWaiting();
                FXREADER.EndConfirmPassword();
				_pPDFDoc = pdfDoc;
				
                _AppState = FXREADER.AppState.STATE_DOC_GETED;
				if (_AppState != FXREADER.AppState.STATE_DOC_GETED)
					return false;
				var stLayoutInfo = new LayoutInfo();

				_pMainView = new CMainFrame(_MainFrameID, _LeftPanelID, _TopPanelID,_BottomPanelID, _pPDFDoc, _pPageViewRender, stLayoutInfo, _self);
				_self.OnResize();
				 
				_BindMouseEvent();
				_self.StepProgress();
				_LoadPlugins();
				if(!_self.CanBePrint() && Config.disablePrint)
				{
					_self.DisablePrint();
				}
				
				_self.OnDocumentOpened();
				_self.OnDocPageIndexUpdated(-1,0);
					
			}
		}
	    
        
        

        this.IsDebugMode = function () { return _bDebugMode; };

        /**
         * @ignore
         * @description 设置调试模式
         * @param bDebug  是否调试模式
         */
        this.SetDebugMode = function (bDebug) {
            _bDebugMode = bDebug;
        };

        this.CallAllPlugin = function () {
            _RegisterBaseModule();
        };



        function _GetLanguage() {
            var en = require("./Lang/en-us");
            var zh = require("./Lang/zh-cn");
            _Language = Languages[_LanguageName];
        }

        function _GetProgress() {
            var nPluginCnt = 0;
            for (var key in _PluginListMap) {
                nPluginCnt++;
            }
            if (nPluginCnt > 0) {
                nPluginCnt += 1; //加上1，是加上初始解析文件这一操作
                return _nStepLoadCnt / nPluginCnt;
            } else {
                return 1;
            }
        }

        this.StepProgress = function () {
            _nStepLoadCnt += 1;
        };

        this.GetImgUrlPattern = function()
        {
        	return _ImgUrlPattern;
        };
        
        this.CanBePrint = function()
        {
        	return (_DocPemission & FXREADER.PER_PRINT_LIMITED) == 0;
        };

        //注册基础插件;
        function _RegisterBaseModule() {
            var pHandTool = new CReader_HandToolHandler();
            _self.RegisterToolHandler(pHandTool);
            _self.SetCurToolHandler(pHandTool);

            var pluginsConfigCookie = FXREADER.Config.Plugins.load;
            
           
           //Annot插件;
          if (pluginsConfigCookie.Annot === true) {
            	var AnnotPluginModule = require('./Plugins/Annot/AnnotPlugin.js');
                _self.RegisterPlugin(AnnotPluginModule);
            }
            
          //Find插件;
            if (pluginsConfigCookie.FindTool === true) {
                var FindToolPluginModule = require('./Plugins/FindTool/FindToolPlugin.js');
                _self.RegisterPlugin(FindToolPluginModule);
            }

            //Navigation Panel插件;
            var pNavigationPlugin = null;
            if (pluginsConfigCookie.NavigationPanel === true) {
               var NavigationPanelPluginModule = require('./Plugins/NavigationPanel/NavigationPanelPlugin.js');
               pNavigationPlugin = _self.RegisterPlugin(NavigationPanelPluginModule);
            }
            
          
            //Bookmark插件;
            if (pNavigationPlugin != null && pluginsConfigCookie.Bookmark === true) {
                var BookmarkPluginModule = require('./Plugins/Bookmark/BookmarkPlugin.js');
                var pBookmarkPlugin = _self.RegisterPlugin(BookmarkPluginModule);
                //添加Bookmark到Navigation Panel;
                if (pBookmarkPlugin != null) {
                    pNavigationPlugin.AddChildPanel(pBookmarkPlugin, true);
                }
            }
            
          //Thumbnail插件;
            if (pNavigationPlugin != null && pluginsConfigCookie.Thumbnail === true) {
                var ThumbnailPluginModule = require('./Plugins/Thumbnail/ThumbNailPlugin.js');
                var pThumbNailPlugin = _self.RegisterPlugin(ThumbnailPluginModule);
                //添加Thumbnail到Navigation Panel;
                if (pThumbNailPlugin != null) {
                    pNavigationPlugin.AddChildPanel(pThumbNailPlugin, true);
                }
            }
            
            if (pluginsConfigCookie.DocProperties === true) {
                var pDocPropertiesPluginModule = require('./Plugins/DocProperties/DocPropertiesPlugin.js');
                _self.RegisterPlugin(pDocPropertiesPluginModule);
            }
            //Form插件;
           // if (pluginsConfigCookie.Form === true) {
            //    var pFormPluginModule = require('./Plugins/Form/FormPlugin.js');
            //    _self.RegisterPlugin(pFormPluginModule);
            //}
            
            //TextSelection插件;
            if (pluginsConfigCookie.TextSelection === true) {
                var pTextSelectionPluginModule = require('./Plugins/TextSelection/TextSelectionPlugin.js');
                _self.RegisterPlugin(pTextSelectionPluginModule);
            }

            
            if (pluginsConfigCookie.ToolBar === true) {
            	var pToolBarPluginModule = require('./Plugins/Toolbar/RibbonToolBarPlugin.js');
                _self.RegisterPlugin(pToolBarPluginModule);
                var pStatusBarPluginModule = require('./Plugins/Toolbar/RibbonStatusBar.js');
                _self.RegisterPlugin(pStatusBarPluginModule);
            }
            
            //Menu插件;
            if (pluginsConfigCookie.Menu === true) {
                var pMenuPluginModule = require('./Plugins/Menu/MenuPlugin.js');
                _self.RegisterPlugin(pMenuPluginModule);
            }
            /*===end PC===*/
            
            /*===begin Wap===*/
            /*
            //Find插件;
            if (pluginsConfigCookie.FindTool === true) {
                var FindToolPluginModule = require('./Plugins/FindTool/FindToolPlugin.js');
                _self.RegisterPlugin(FindToolPluginModule);
            }

            
            var pNavigationPlugin = null;
            if (pluginsConfigCookie.NavigationPanel === true) {
                var NavigationPanelPluginModule = require('./Plugins/NavigationPanel/WapNavigationPanelPlugin.js');
                pNavigationPlugin = _self.RegisterPlugin(NavigationPanelPluginModule);
            }
            
            //Bookmark插件;
            if (pNavigationPlugin != null && pluginsConfigCookie.Bookmark === true) {
                var BookmarkPluginModule = require('./Plugins/Bookmark/WapBookmarkPlugin.js');
                var pBookmarkPlugin = _self.RegisterPlugin(BookmarkPluginModule);
                if (pBookmarkPlugin != null) {
                    pNavigationPlugin.AddChildPanel(pBookmarkPlugin, true);
                }
            }
            
            //Thumbnail插件;
            if (pNavigationPlugin != null && pluginsConfigCookie.Thumbnail === true) {
                var ThumbnailPluginModule = require('./Plugins/Thumbnail/ThumbNailPlugin.js');
                var pThumbNailPlugin = _self.RegisterPlugin(ThumbnailPluginModule);
                //添加Thumbnail到Navigation Panel;
                if (pThumbNailPlugin != null) {
                    pNavigationPlugin.AddChildPanel(pThumbNailPlugin, true);
                }
            }
           
            
            //ToolBar插件;
            if (pluginsConfigCookie.ToolBar === true) {
            	var pToolBarPluginModule = require('./Plugins/Toolbar/WapRibbonToolbarPlugin.js');;
                _self.RegisterPlugin(pToolBarPluginModule);
               
            }*/
            /*===end Wap===*/
        }

        function _LoadPlugins() {
            $.each(_PluginListMap, function (key, plugin) {
                try {
                    plugin.PIInit();
                }
                catch (ex) {
                	throw ex;
                }
            });
        }

        function _CreatePDFDoc(docinfo, nShowPage, nShowPageCount) {
            try {
                _pPDFDoc = new FXREADER.PDFData.CPDF_Document(parseInt(docinfo.doctype));
                _pPDFDoc.SetShowPageRange(nShowPage, nShowPageCount);
                for (var i = 0; i < docinfo.PagesInfo.length; i++) {
                    var pPDFPage = new FXREADER.PDFData.CPDF_Page(docinfo.PagesInfo[i]);
                    _pPDFDoc.AddPage(pPDFPage);
                }
                if (docinfo && docinfo.dppinfo && docinfo.dppinfo.ppt) {
                    var pDocProperties = new FXREADER.PDFData.CPDF_DocProperties(docinfo.dppinfo.ppt);
                    _pPDFDoc.SetDocProperties(pDocProperties);
                }
                else
                    _pPDFDoc.SetDocProperties(null);
                _AppState = FXREADER.AppState.STATE_DOC_GETED;
            }
            catch (ex) {
                throw ex;
                return false;
            }

            return true;
        }
        /**
         * @description Get the ID of the top panel.
         * @return {String} ID of the top panel.
         */
        this.GetTopPanelID = function () {
            return _TopPanelID;
        };

        this.GetBottomPanelID = function()
        {
        	return _BottomPanelID;
        };
        
        //初始化工作，包括获取文档信息，构建视图，加载插件等;
        function _Init(docinfo, nShowPage, nShowPageCount) {
            try {
                _CreatePDFDoc(docinfo, nShowPage, nShowPageCount);
                if (_AppState != FXREADER.AppState.STATE_DOC_GETED)
                    return false;
                _pPageViewRender = new CImgPageViewRender(_ImgUrlPattern);
                var stLayoutInfo = new LayoutInfo();

                _pMainView = new CMainFrame(_MainFrameID, _LeftPanelID, _TopPanelID,_BottomPanelID, _pPDFDoc, _pPageViewRender, stLayoutInfo, _self);
                _self.OnResize();
            }
            catch (ex) {
                throw ex;
                return false;
            }
            return true;
        }

        function _BindMouseEvent() {
            var jqDocViewContainer = $("#" + _self.GetMainView().GetDocView().GetDocViewContainerID());
            if (jqDocViewContainer == null) {
                throw new Error('Doc view container is not exsits!');
            }
            new MouseBindingHandler(jqDocViewContainer, _self).bind();
            //下面绑定MarinFrm 消息
            var jqMainFrm = $("#" + _self.GetMainView().GetMainFrameID());
            jqMainFrm.mousedown(function (event) {
                //左键;
                if (event.button == 0 || event.button == 1) {
                    _self.OnMainFrmLButtonDown(event);
                }
                return true;
            });

            jqMainFrm.mousemove(function (event) {
                _self.OnMainFrmMouseMove(event);
            });

            jqMainFrm.mouseup(function (event) {
                _self.OnMainFrmLButtonUp(event);
            });

            jqMainFrm.mouseleave(function (event) {
                _self.OnMainFrmMouseLeave(event);
            });


            jqMainFrm.mouseout(function (event) {
                _self.OnMainFrmMouseOut(event);
            });

        }

        function _ReparseDoc(jqPassword, jqErrInfo) {
            _bFirstTimeParse = false;

            var psd_value = jqPassword.val();
            psd_value = escape(psd_value);
            var data = { fileid: _FileID, fname: _FileName, psd: psd_value };
            function _ParseCallBack(error) {
                if (error == 3) {
                    jqErrInfo.html("<font color='red'>" + _Language.ParseError.PasswordIncorrect + "</font>");
                }
            }
            //FXREADER.Waiting({});
            _self.GetDoc(data, _ParseCallBack,Config.maxManifestRetryCount);
        }

        function _PopupParserFailDlg(errType,status) {
        	var dlgTitle = null;
            switch (errType) {
                case FXREADER.PDFError.ERROR_COM_CALL:
                case FXREADER.PDFError.ERROR_PDFPARSE_FILE:
                    FXREADER.Alert(dlgTitle, _Language.ParseError.FailToOpen);
                    break;
                case FXREADER.PDFError.ERROR_PDFPARSE_FORMAT:
                    FXREADER.Alert(dlgTitle, _Language.ParseError.ErrFormat);
                    break;
                case FXREADER.PDFError.ERROR_PDFPARSE_HANDLER:
                    FXREADER.Alert(dlgTitle, _Language.ParseError.ErrHandle);
                    break;
                case FXREADER.PDFError.ERROR_PDFPARSE_CERT:
                    FXREADER.Alert(dlgTitle, _Language.ParseError.ErrCert);
                    break;
                case FXREADER.PDFError.ERROR_PDFPARSE_PAGE_COUNT_EXCEED:
                	FXREADER.Alert(dlgTitle, _Language.ParseError.ErrPage);
                	break;
                default:
                	if(status == FXREADER.ConversionState.ServiceBusy)
                	{
                		FXREADER.Alert(dlgTitle, _Language.ParseError.ServiceBusy);
                	}
                	else
                    {
                		FXREADER.Alert(dlgTitle, _Language.ParseError.UnKnown+status);
                    }
                    break;
            }
        }


        //public methods
        /**
         * @description set current language.
         * @param {String} szLangName name of the language to set("en-us" or "zh-cn").
         */
        this.SetLanguage = function (szLangName) {
            _LanguageName = szLangName;
            _Language = Languages[szLangName];
        };
        /**
         * @description Get the language. 
         * @return {Array} language object in JSON format.
         */
        this.GetLanguage = function () {
            return _Language;
        };


        this.GetPluginsCookie = function () {
            return FXREADER.Config.Plugins.load;
        };
        
        this.DisablePrint = function()
        {
        	var css = 'body { display:none; }',
            head = document.head || document.getElementsByTagName('head')[0],
            style = document.createElement('style');

	        style.type = 'text/css';
	        style.media = 'print';
	        if (style.styleSheet){
	          style.styleSheet.cssText = css;
	        } else {
	          style.appendChild(document.createTextNode(css));
	        }
	
	        head.appendChild(style);
        };
        
        /* 从网络上获取文档的概要信息，包括页面大小等*/
        this.GetDoc = function (data, callback,retryCount) {
        	if (retryCount <= 0) {
        		FXREADER.CloseWaiting();
                _PopupParserFailDlg(FXREADER.PDFError.ERROR_UNKNOWN,FXREADER.ConversionState.ServiceBusy);
                return;
            }
            if (data == null)
                data = { fileid: _FileID, fname: _FileName };
            $.ajax({
                url: FXREADER.Config.Url.GetBaseInfo,
                type: 'POST',
                dataType: 'json',
                data: data,

                success: function (response) {
                    var error = response.error;
                    callback && callback(error);
                    if (error != 0) {
                        if (error == FXREADER.PDFError.ERROR_PDFPARSE_PASSWORD) {
                        	FXREADER.CloseWaiting();
                        	$('.ui-widget-overlay').css('z-index', "1001");
                            _bFirstTimeParse && FXREADER.ConfirmPassword("", _Language.ParseError.EnterPassword, _ReparseDoc);
                        }
                        else {
                        	 
                        	 if (FXREADER.Common.IsNeedRetry(response.status)) {
                                 setTimeout(function () { _self.GetDoc(data, callback, retryCount - 1); }, Config.requestRetryInterval);
                                 return;
                             }
                        	 else if(response.status == FXREADER.ConversionState.ServiceBusy)
                        	 {
                        		 FXREADER.EndConfirmPassword();
                        		 FXREADER.CloseWaiting();
                            	 _PopupParserFailDlg(error,response.status);
                        	 }
                             else
                             {
                            	 FXREADER.EndConfirmPassword();
                            	 FXREADER.CloseWaiting();
                            	 _PopupParserFailDlg(error,response.status);
                            	 
                             }
                        }
                        return;
                    }

                    try {
                    	FXREADER.CloseWaiting();
                        FXREADER.EndConfirmPassword();
                        _CanDownloadPDF = response.CanDownload;
                        _DocPemission = response.DocPemission;
                        var docInfo = $.parseJSON(response.docinfo);
                        //初始化App;
                        if (_Init(docInfo, response.startShowPage, response.showPageCount)) {
                        ////hjp,add
                        	Config.Url.GetPageBGImg += "?";
                           /* if (_self.GetPluginsCookie().Form === true && _self.GetPDFDoc().GetDocType() == FXREADER.PDFData.DocType.FORM) {
                            	Config.Url.GetPageBGImg += "form=true&";
                            }*/
                            ////
                            _BindMouseEvent();
                            //_RegisterBaseModule();
                            // ProgressBar.Setup(_GetProgress);
                            _self.StepProgress();
                            _LoadPlugins();
                            if(!_self.CanBePrint() && Config.disablePrint)
                            {
                            	_self.DisablePrint();
                            }
                            
                            _self.OnDocumentOpened();
                            _self.OnDocPageIndexUpdated(-1,0);
                            $(".fwr-custom-select").each(function(){
                                $(this).wrap( "<span class='fwr-select-wrapper'></span>" );
                                $(this).after("<span class='holder'></span>");
                            });
                            $(".fwr-custom-select").change(function(){
                                var selectedOption = $(this).find(":selected").text();
                                $(this).next(".holder").text(selectedOption);
                            }).trigger('change');
                        }
                    }
                    catch (ex) {
                        ProgressBar.HideProgressBar();
                        //throw ex; // new Error('Init App Error!');
                        return false;
                    }
                },
                error: function () {
                    FXREADER.Alert(_Language.CommonDialog.DefaultDlgTitle, _Language.ParseError.LoadError);
                    ProgressBar.HideProgressBar();
                    FXREADER.CloseWaiting();
                }
            });
        };
        /**
         * @description Check whether the user has permission to download the source PDF file.
         * @return {Boolean} if the user has permission to download the source PDF file, return true, otherwise, return false.
         */
        this.CanDownloadPDF = function () {
            return _CanDownloadPDF;
        };

        this.GetDocPemission = function () {
            return _DocPemission;
        };

        this.GetTextManager = function()
        {
        	if(_textManager == null)
        		_textManager = new FXREADER.PDFData.Text.TextManager(_self);
        	return _textManager;	
        };
        /**
         * @description Initialize the App instance.
         */
        this.InitInstance = function () {
            ProgressBar.Setup(_GetProgress);
            FXREADER.Waiting({});
            this.LoadDocument();
        };
        
        this.GetEidtorApp = function(){
        	return _EditorApp;
        };
        
        this.IsFitWidth = function()
        {
        	return _bFitWidth;
        };
        
        this.SetFitWidth = function(bFitWidth)
        {
        	_bFitWidth = bFitWidth;
        };
        //绑定事件
        this.CreateCmdAndCmdUI = function() {
        	this.AddCommandUI({
                UIName: "First Page",
                CommandName: 'GoFirstPage',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnfirst' class='fwr_toolbar_btn  fwr_toobar_image_btn fwr_toobar_first_page_dis' title='GoFirstPage' cmd='" + "GoFirstPage" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnfirst', "fwr_toobar_first_page_nor", "fwr_toobar_first_page_dis", data.state);
                },
                Init: function () {
                	if(_dtype === 1){
                		FXREADER.Common.UpdateBtnState('btnfirst', "fwr_toobar_first_page_nor", "fwr_toobar_first_page_dis",_self.GetEidtorApp().GetCurPageIndex() != 0);
                	}else{
                		FXREADER.Common.UpdateBtnState('btnfirst', "fwr_toobar_first_page_nor", "fwr_toobar_first_page_dis", this.GetMainView().GetDocView().GetCurPageIndex() != 0);
                	}
                }
            });
        	this.AddCommand({
                state: false,
                name: "GoFirstPage",
                exec: function (data) {
                	if(_dtype === 1){
                		_self. GetEidtorApp().OnGotoFirstPage();
                	}else{
                		this.GetMainView().GetDocView().GotoPage(0);
                	}
                }
            });
        	this.AddCommandUI({
                UIName: "Prev Page",
                CommandName: 'GoPrevPage',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnpre' class='fwr_toolbar_btn fwr_toobar_prev_page_dis fwr_toobar_image_btn' title='GoPrevPage' cmd='" + "GoPrevPage" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnpre', "fwr_toobar_prev_page_nor", "fwr_toobar_prev_page_dis", data.state);
                },
                Init: function () {
                	if(_dtype === 1){
                		FXREADER.Common.UpdateBtnState('btnpre', "fwr_toobar_prev_page_nor", "fwr_toobar_prev_page_dis", _self.GetEidtorApp().GetCurPageIndex() != 0);
                	}else{
                		FXREADER.Common.UpdateBtnState('btnpre', "fwr_toobar_prev_page_nor", "fwr_toobar_prev_page_dis", _self.GetCurPageIndex() != 0);
                	}
                }
            });
        	this.AddCommand({
                state: false,
                name: "GoPrevPage",
                exec: function (data) {
                	if(_dtype === 1){
                		_self. GetEidtorApp().OnGotoPreviousPage();
                	}else{
                		_self.GetMainView().GetDocView().GoPrevPage();
                	}
                }
            });

            this.AddCommandUI({
                UIName: "Next Page",
                CommandName: 'GoNextPage',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnnext' class='fwr_toolbar_btn fwr_toobar_next_page_dis fwr_toobar_image_btn' title='GoNextPage' cmd='" + "GoNextPage" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnnext', "fwr_toobar_next_page_nor", "fwr_toobar_next_page_dis", data.state);
                },
                Init: function () {
                	if(_dtype === 1){
                		FXREADER.Common.UpdateBtnState('btnnext', "fwr_toobar_next_page_nor", "fwr_toobar_next_page_dis", _self.GetEidtorApp().GetCurPageIndex() != _self.GetEidtorApp().GetPageCount() - 1);
                	}else{
                		FXREADER.Common.UpdateBtnState('btnnext', "fwr_toobar_next_page_nor", "fwr_toobar_next_page_dis", _self.GetCurPageIndex() != _self.GetPageCount() - 1);
                	}
                }
            });
            this.AddCommand({
                state: false,
                name: "GoNextPage",
                exec: function (data) {
                	if(_dtype === 1){
                		_self. GetEidtorApp().OnGotoNextPage();
                	}else{
                    _pReaderApp.GetMainView().GetDocView().GoNextPage();
                	}
                }
            });

            this.AddCommandUI({
                UIName: "Last Page",
                CommandName: 'GoLastPage',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnlast' class='fwr_toolbar_btn fwr_toobar_last_page_dis fwr_toobar_image_btn' title='GoLastPage' cmd='" + "GoLastPage" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnlast', "fwr_toobar_last_page_nor", "fwr_toobar_last_page_dis", data.state);
                },
                Init: function () {
                	if(_dtype === 1){
                		FXREADER.Common.UpdateBtnState('btnlast', "fwr_toobar_last_page_nor", "fwr_toobar_last_page_dis", _self.GetEidtorApp().GetCurPageIndex() != _self.GetEidtorApp().GetPageCount() - 1);
                	}else{
                		FXREADER.Common.UpdateBtnState('btnlast', "fwr_toobar_last_page_nor", "fwr_toobar_last_page_dis", _self.GetCurPageIndex() != _self.GetPageCount() - 1);
                	}
                }
            });
            this.AddCommand({
                state: false,
                name: "GoLastPage",
                exec: function (data) {
                	if(_dtype === 1){
                		_self. GetEidtorApp().OnGotoLastPage();
                	}else{
                		_pReaderApp.GetMainView().GetDocView().GotoPage(_pReaderApp.GetMainView().GetDocView().GetPageCount() - 1);
                	}
                }
            });
            this.AddCommandUI({
                UIName: "GotoPage",
                CommandName: "UpdatePage",
                State: 1,
                CreateHtmlContentFunc: function () {
                	if(FXREADER.Environment.chrome)
                		return "<div class='fwr_toolbar_page_control'><input id='textpagenum' class='fwr_text_input_chrome fwr_display_inline fwr_toolbar_page_control_pagenum' type='text' value='1' disabled='disabled'/><span id='totalPages' class='fwr_label fwr_toolbar_page_control_pagecnt' ></span></div>";
                	else
                		return "<div class='fwr_toolbar_page_control'><input id='textpagenum' class='fwr_text_input fwr_display_inline fwr_toolbar_page_control_pagenum' type='text' value='1' disabled='disabled'/><span id='totalPages' class='fwr_label fwr_toolbar_page_control_pagecnt' ></span></div>";
                },
                Init: function () {
                	if(_dtype === 1){
                		_self. GetEidtorApp().OnGotoPage();
                		var jqPageNum = $("#textpagenum");
	                    jqPageNum.removeAttr("disabled");
	                    $("#totalPages").html(" / " + _self. GetEidtorApp().GetPageCount());
	                    jqPageNum.bind("click",function(){
	                        return true;
	                    });
	                    jqPageNum.bind("keypress",function(d){
	                    	 if (!$(this).hasClass("fwr_button_disabled") && d.keyCode == "13") {
		                            $(this).val() > _self. GetEidtorApp().GetPageCount() && $(this).val(_self. GetEidtorApp().GetPageCount());
		                            ($(this).val() < 1 || isNaN($(this).val())) && $(this).val(1);
		                            _self. GetEidtorApp().OnGotoPage();
		                        }
		                        return true;
	                    });
                	}else{
	                    var jqPageNum = $("#textpagenum");
	                    jqPageNum.removeAttr("disabled");
	                    $("#totalPages").html(" / " + _self.GetPageCount());
	
	                    jqPageNum.bind("click", function () {
	                        this.focus();
	                        return true;
	                    });
	                    jqPageNum.bind("keypress", function (d) {
	                        if (!$(this).hasClass("fwr_button_disabled") && d.keyCode == "13") {
	                            $(this).val() > _self.GetPageCount() && $(this).val(_self.GetPageCount());
	                            ($(this).val() < 1 || isNaN($(this).val())) && $(this).val(1);
	                            _self.GotoPage(parseInt($(this).val() - 1));
	                        }
	                        return true;
	                    });
                }
                },
                OnCommandStateChange: function (data) {
                    $("#textpagenum").val(data.state);
                }
            });
            this.AddCommand({
                state: 1,
                name: "UpdatePage",
                exec: function (data) {
                }
            });
            this.AddCommandUI({
                UIName: "ZoomIn",
                CommandName: 'ZoomIn',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnzoomIn' class='fwr_toolbar_btn fwr_toobar_image_btn fwr_toobar_zoomin_dis'  title='Zoom In' cmd='" + "ZoomIn" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnzoomIn', "fwr_toobar_zoomin_nor", "fwr_toobar_zoomin_dis", data.state);
                },
                Init: function () {
                	var scale = null;
                	if(_dtype === 1){
                		scale = _self. GetEidtorApp().GetZoomFactor();
                	}else{
                		scale = _self.GetScale();
                	}
	                    var maxScale = scale > Config.maxZoomSize ? scale : Config.maxZoomSize;
	                    var pCommandZoomIn = _self.GetCommand('ZoomIn');
	                    if (scale >= maxScale) {
	                        pCommandZoomIn && pCommandZoomIn.SetState(false);
	                    }else {
	                        pCommandZoomIn && pCommandZoomIn.SetState(true);
	                    }
                	
                }
            });
            this.AddCommand({
                state: false,
                name: "ZoomIn",
                exec: function (data) {
                	if(_dtype === 1){
                		_self.GetEidtorApp().OnZoomIn();
                		var jqZoomSel = $("#zoomSel");
                		jqZoomSel.attr("value", "75%");
                	}else{
	                    var scale = _pViewLayout.GetFitWidthScale(true);
	                    var curZoom = _self.GetScale();
	                    var maxScale = scale > Config.maxZoomSize ? scale : Config.maxZoomSize;
	                    if (curZoom >= maxScale)
	                        return;
	                    var tmpZoom = curZoom;
	                    //var zoomIndex = -1;
	                    var fitwidthNextZoomIndex = -1;
	                    for (var i = 0; i < Config.zoomList.length; i++) {
	                        if (curZoom == Config.zoomList[i]) {
	                            if (i + 1 < Config.zoomList.length) {
	                                zoomIndex = i + 1;
	                                tmpZoom = Config.zoomList[i + 1];
	                            }
	                        }
	                        else if (Config.zoomList[i] > curZoom) {
	                            if (fitwidthNextZoomIndex == -1) {
	                                fitwidthNextZoomIndex = i;
	                            }
	                        }
	                    }
	
	                    if (_self.IsFitWidth()) {
	                        if (fitwidthNextZoomIndex != -1)
	                            curZoom = Config.zoomList[fitwidthNextZoomIndex];
	                        _self.SetFitWidth(false);
	                    }else {
	                        if (tmpZoom < scale) {
	                            curZoom = tmpZoom;
	                            _self.SetFitWidth(false);
	                        }else if (tmpZoom > scale) {
	                            if (curZoom < scale) {
	                                curZoom = scale;
	                                _self.SetFitWidth(true);
	                            }else {
	                                curZoom = tmpZoom;
	                                _self.SetFitWidth(false);
	                            };
	                        }else {
	                            curZoom = tmpZoom;
	                            _self.SetFitWidth(true);
	                        };
	                    }
	                    _self.OnZoom(curZoom);
	                   
	                }
                }
            });
            this.AddCommandUI({
                UIName: "ZoomOut",
                CommandName: 'ZoomOut',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnzoomOut' class='fwr_toolbar_btn fwr_toobar_image_btn fwr_toobar_zoomout_dis' ' title='Zoom Out' cmd='" + "ZoomOut" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                    FXREADER.Common.UpdateBtnState('btnzoomOut', "fwr_toobar_zoomout_nor", "fwr_toobar_zoomout_dis", data.state);
                },
                Init: function () {
                	if(_dtype === 1){
                		var scale = _self.GetEidtorApp().GetZoomFactor();
	                    var minScale = scale < Config.minZoomSize ? scale : Config.minZoomSize;
	                    var pCommandZoomOut = _self.GetCommand('ZoomOut');
	                    if (scale <= minScale) {
	                        pCommandZoomOut && pCommandZoomOut.SetState(false);
	                    }else {
	                        pCommandZoomOut && pCommandZoomOut.SetState(true);
	                    }
                	}else{
	                    var scale = _self.GetScale();
	                    var minScale = scale < Config.minZoomSize ? scale : Config.minZoomSize;
	                    var pCommandZoomOut = _pReaderApp.GetCommand('ZoomOut');
	                    if (scale <= minScale) {
	                        pCommandZoomOut && pCommandZoomOut.SetState(false);
	                    }else {
	                        pCommandZoomOut && pCommandZoomOut.SetState(true);
	                    }
                	}
                }
            });
            this.AddCommand({
                state: false,
                name: "ZoomOut",
                exec: function (data) {
                	if(_dtype === 1){
                		_self.GetEidtorApp().OnZoomOut();
                	}else{
	                    var scale = _pViewLayout.GetFitWidthScale(true);
	                    var curZoom = _self.GetScale();
	                    var minScale = scale < Config.minZoomSize ? scale : Config.minZoomSize;
	                    if (curZoom <= minScale)
	                        return;
	                    var tmpZoom = curZoom;
	                    //var zoomIndex = -1;
	                    var fitwidthNextZoomIndex = -1;
	                    for (var i = Config.zoomList.length - 1; i >= 0; i--) {
	                        if (curZoom == Config.zoomList[i]) {
	                            if (i - 1 >= 0) {
	                                zoomIndex = i - 1;
	                                tmpZoom = Config.zoomList[i - 1];
	                            }
	                        }else if (Config.zoomList[i] < curZoom) {
	                            if (fitwidthNextZoomIndex == -1) {
	                                fitwidthNextZoomIndex = i;
	                            }
	                        }
	                    }
	                    if (_self.IsFitWidth()) {
	                        if (fitwidthNextZoomIndex != -1)
	                            curZoom = Config.zoomList[fitwidthNextZoomIndex];
	                        _self.SetFitWidth(false);
	                    }
	                    else {
	                        if (tmpZoom > scale) {
	                            curZoom = tmpZoom;
	                            _self.SetFitWidth(false);
	                        }else if (tmpZoom < scale) {
	                            if (curZoom > scale) {
	                                curZoom = scale;
	                                _self.SetFitWidth(true);
	                            }else {
	                                curZoom = tmpZoom;
	                                _self.SetFitWidth(false);
	                            }
	                        }else {
	                            curZoom = tmpZoom;
	                            _self.SetFitWidth(true);
	                        }
	                    }
	
	                    _self.OnZoom(curZoom);
                	}
                }
            });
            function _getCurrentZoomList()
            {
             	var fitWidthScale = _pViewLayout.GetFitWidthScale(true);
            	var zoomList = [];
            	var bFitWidthAppended = false;
            	for (var i = 0; i < Config.zoomList.length; i++) {
                    if(Config.zoomList[i] <= fitWidthScale)
                    	zoomList.push(Config.zoomList[i]);
                    else
                    {
                    	if(!bFitWidthAppended)
                    	{
                    		zoomList.push(_Language.CommandUI.FitWidth);
                    		bFitWidthAppended = true;
                    	}
                    	zoomList.push(Config.zoomList[i]);
                    }
                }
            	if(!bFitWidthAppended)
            	{
            		zoomList.push(fitWidthScale);
            	}
            	return zoomList;
            }
            this.AddCommandUI({
                UIName: "ZoomSlider",
                CommandName: 'OnZoom',
                State: false,
                CreateHtmlContentFunc: function () {
                    var html = "<div id='zoom_select_slider' class='fwr_toobar_image_btn' style='width:80px;margin-top:9px;'></div>";
                    return html;
                },
                OnCommandStateChange: function (data) {
                	var curZoom = _self. GetEidtorApp().GetZoomFactor();
                	var currentValue = -1;
                	var zoomList = _self. GetEidtorApp().getCurrentZoomList();
                	for (var i = 0; i < zoomList.length; i++) {
                		if(zoomList[i] == curZoom || (zoomList[i]=="FitWidth" && _self.IsFitWidth()))
                		{
                			currentValue = i+1;
                			break;
                		}
                	}
                	$("#zoom_select_slider" ).slider('value',currentValue);   
                },
                Init: function () {
                	if(_dtype === 1){
                		var currentValue = 3;
                		var zoomList = _self. GetEidtorApp().getCurrentZoomList();
                		console.log(zoomList);
                		$("#zoom_select_slider" ).slider({
	                	      range: "max",
	                	      min: 1,
	                	      max: Config.zoomList.length,
	                	      value: currentValue,
	                	      slide: function( event, ui ) {
	                	    	  var zoomSelected = zoomList[ui.value-1];
	                	    	  var curZoomFactor = _self. GetEidtorApp().GetZoomFactor();
	                	    	  console.log("现在的倍率:" + curZoomFactor + "要变成的倍率:" + zoomSelected);
	                	    	  _self. GetEidtorApp().SetZoomDiff(zoomSelected,curZoomFactor);
	                	    	  if(zoomSelected > curZoomFactor){
	                	    		  _self.GetEidtorApp().OnZoomIn();
	                	          }else if(zoomSelected < curZoomFactor){
	                	        	  _self.GetEidtorApp().OnZoomOut();
	                	          }
	                	      }
	                	});
                	}else{
	                	var currentValue = -1;
	                	var curZoom = _self.GetScale();
	                	var zoomList = _getCurrentZoomList();
	                	for (var i = 0; i < zoomList.length; i++) {
	                		if(zoomList[i]==curZoom || (zoomList[i]==_Language.CommandUI.FitWidth && _self.IsFitWidth()))
	                		{
	                			currentValue = i+1;
	                			break;
	                		}
	                	}
	                	$("#zoom_select_slider" ).slider({
	                	      range: "max",
	                	      min: 1,
	                	      max: Config.zoomList.length+1,
	                	      value: currentValue,
	                	      slide: function( event, ui ) {
	                	    	  var zoomList = _getCurrentZoomList();
	                	    	  var zoomSelected = zoomList[ui.value-1];
	                	    	  if(zoomSelected == _Language.CommandUI.FitWidth)
		                       	  {
		                       		   if(!_self.IsFitWidth())
		                       		   {
		                       			   _self.SetFitWidth(true);
		                              		   var fitScale = _pViewLayout.GetFitWidthScale(true);
		                           		   _self.OnZoom(fitScale);
		                       		   }
		            
		                       	   }
		                       	   else
		                       	   {
		                       		   _self.SetFitWidth(false);
		                                  var curZoom = zoomSelected;
		                                  _self.OnZoom(curZoom);
		                       	   }
		                	     }
	                	});
                }
                }
            });
            this.AddCommandUI({
                UIName: "FitWidth",
                CommandName: 'FitWidth',
                State: false,
                CreateHtmlContentFunc: function () {
                    return "<a id='btnFitWidth' class='fwr_toolbar_btn fwr_toobar_image_btn fwr_toobar_fitwidth_dis' title='Fit Width' cmd='" + "FitWidth" + "'></a>";
                },
                OnCommandStateChange: function (data) {
                	if(data.state == false)
                	{
                		FXREADER.Common.UpdateBtnState("btnFitWidth", "fwr_toobar_fitwidth_dis", "fwr_toobar_fitwidth_active", true);
                	}else{
                		FXREADER.Common.UpdateBtnState("btnFitWidth", "fwr_toobar_fitwidth_active", "fwr_toobar_fitwidth_dis", true);
                	}
                },
                Init: function () {
                		var pCommandFitWidth = _self.GetCommand('FitWidth');
                        if (!_self.IsFitWidth()) {
                        	pCommandFitWidth && pCommandFitWidth.SetState(false);
                        }
                        else {
                        	pCommandFitWidth && pCommandFitWidth.SetState(true);
                        }
                	
                }
            });
          this.AddCommand({
                state: false,
                name: "FitWidth",
                exec: function (data) {
                	if(_dtype === 1){
                		  var zoomSelected = 1;
	           	    	  var curZoomFactor = _self. GetEidtorApp().GetZoomFactor();
	           	    	_self. GetEidtorApp().SetZoomDiff(zoomSelected,curZoomFactor);
	           	    	  
	           	    	  if(zoomSelected > curZoomFactor){
	           	    		  _self.GetEidtorApp().OnZoomIn();
	           	          }else if(zoomSelected < curZoomFactor){
	           	        	  _self.GetEidtorApp().OnZoomOut();
	           	          }
	           	    	  
                	}else{
                		_self.FitWidth();
                	}
                }
            });
          this.AddCommandUI({
              UIName: "SelectZoom",
              CommandName: 'OnZoom',
              State: false,
              CreateHtmlContentFunc: function () {
                  var html = "<span class='fwr-select-wrapper'><select id='zoomSel' class='fwr_text_input fwr_toolbar_zoomsel_select fwr-custom-select'  disabled='disabled'>";
                  for (var i = 0; i < Config.zoomList.length; i++) {
                      html += "<option value='" + Config.zoomList[i] * 100 + "'>" + Config.zoomList[i] * 100 + "%</option>";
                  }
                  html += "<option value='Fit Width'>Fit Width</option></select>";
                  html += "</span>";
                  return html;
              },
              OnCommandStateChange: function (data) {
                  var jqZoomSel = $("#zoomSel");
                  if(_self.IsFitWidth())
                  {
                  	jqZoomSel.attr("value", _Language.CommandUI.FitWidth);
                  	var jq =jqZoomSel.parent().children(".holder");
                  	jq.text(selectedOption);
                  	jq.text(_Language.CommandUI.FitWidth);
                  }else{
                  	jqZoomSel.attr("value", data.state * 100);
                  	var selectedOption = jqZoomSel.find(":selected").text();
                  	var jq =jqZoomSel.parent().children(".holder");
                  	jq.text(selectedOption);
                  }
              },
              Init: function () {
            	 if(_dtype === 1){
            		 var jqZoomSel = $("#zoomSel");
	                  jqZoomSel.removeAttr("disabled");
	                  var scale = _self. GetEidtorApp().GetZoomFactor();
	                  if(_self.IsFitWidth()) {
	                  	//jqZoomSel.attr("value", _Language.CommandUI.FitWidth);
	                  }else{
	                  	jqZoomSel.attr("value", scale * 100);
	                  }
	                 jqZoomSel.bind("change", function () {
	              	   if(jqZoomSel.val() == _Language.CommandUI.FitWidth){
	              		   if(!_self.IsFitWidth()) {
	              			   _self.SetFitWidth(true);
	                  		 _self. GetEidtorApp().OnZoomOut();
	              		   }
	   
	              	   }else {
	              		   _self.SetFitWidth(false);
	                         var curZoom = jqZoomSel.val() / 100;
	                         _self.OnZoom(curZoom);
	                         _self. GetEidtorApp().OnZoomIn();
	              	   }
	 
	                  });
              	}else{
	                  var jqZoomSel = $("#zoomSel");
	                  jqZoomSel.removeAttr("disabled");
	                  var scale = _self.GetScale();
	                  if(_self.IsFitWidth()) {
	                  	jqZoomSel.attr("value", _Language.CommandUI.FitWidth);
	                  }else{
	                  	jqZoomSel.attr("value", scale * 100);
	                  }
	                 jqZoomSel.bind("change", function () {
	              	   if(jqZoomSel.val() == _Language.CommandUI.FitWidth){
	              		   if(!_self.IsFitWidth()) {
	              			   _self.SetFitWidth(true);
	                     		   var fitScale = _pViewLayout.GetFitWidthScale(true);
	                  		   _self.OnZoom(fitScale);
	              		   }
	   
	              	   }else {
	              		   _self.SetFitWidth(false);
	                         var curZoom = jqZoomSel.val() / 100;
	                         _self.OnZoom(curZoom);
	              	   }
	 
	                  });
              }
           }
          });

          this.AddCommand({
              state: _self. GetEidtorApp().GetZoomFactor(),
              name: "OnZoom",
              exec: function (data) {
              }
          });
        };

        //////////////////////////////////Command 相关////////////////////////////////////////
        /**
         * @description Add a new command, usually used in toolbar.
         * @param {Object} commandDefination a command defination.
         * @example _self.AddCommand({
         *        state: true,
         *        name: 'CommandName',
         *        exec: function (data) {alert(CommandName);}
         *       });
         * @return {Object} return true if the command has been add successfully, otherwise return false.
         */
        this.AddCommand = function (commandDefination) {
            if (commandDefination == null)
                return false;
            var pNewCommand = new CBaseCommand(_self, commandDefination);
            _CommandList[pNewCommand.GetCommandName()] = pNewCommand;
            return true;
        };
        /**
         * @description Get a command.
         * @param {String} commandName name of the command.
         * @return {FXREADER.CBaseCommand} command object.
         */
        this.GetCommand = function (commandName) {
            return _CommandList[commandName];
        };
        /**
         * @description execute a command.
         * @param {String} commandName name of the command.
 		* @param {Object} data parameters which the command need.
         * @return {Object} the state after execution.
         */
        this.ExecCommand = function (commandName, data) {
            var command = _self.GetCommand(commandName);
            return command.Execute(data);
        };
        /**
         * @description add a UI defination of a command.
         * @param {Object} uiDefination a UI defination.
         * @example _self.AddCommandUI({
         *                UIName: "UIName",
         *                CommandName: "CommandName",
         *                CreateHtmlContentFunc: function () {
         *                    return "<a id='btnHighlight' style='margin-right:4px;height:25px;' class='fwr_toolbar_link_btn fwr_form_highlight_btn_dis' title='" + _Language.Form.HighlightButTitle + "'>" +
         *                           "<img src='about:blank' style='height:10px;width:10px;margin:8px 4px 0px 0px;float:left;'/>" + _Language.Form.HighlightButText + "</a>";
         *                },
         *                Init: function () {
         *                	if (!_self.m_bCanFillForm)
         *              	    {
         *                		obj.children("img").addClass("fwr_form_highlight_btn_img_dis");
         *                		return;
         *                	}
         *                	var obj = $("#btnHighlight");
         *                	obj.children("img").addClass("fwr_form_highlight_btn_img");
         *                	obj.removeClass('fwr_form_highlight_btn_dis').addClass('fwr_toolbar_btn').bind('click', function () {
         *                        _self.ChangeHighlight();
         *                        return false;
         *                    });
         *                }
         *            });
         * @return {Boolean} return true if the UI has been add successfully, otherwise return false.
         */
        this.AddCommandUI = function (uiDefination) {
            if (uiDefination == null)
                return false;
            var pCommandUI = new CCommandUI(_self, uiDefination);
            _CommandUIList[pCommandUI.m_UIName] = pCommandUI;
            return true;
        };
        /**
         * @description Get an UI object.
         * @param {String} commandUIName name of the UI.
         * @return {FXREADER.CCommandUI} UI object.
         */
        this.GetCommandUI = function (commandUIName) {
            return _CommandUIList[commandUIName];
        };
        /**
         * @description Get a list of UI objects.
         * @return {Array.<{FXREADER.CCommandUI}>}  a list of UI objects.
         */
        this.GetCommandUIList = function () {
            return _CommandUIList;
        };
        /**
         * @description Add a menu item defination.
         * @param {Array} menuItemDefination menu item defination.
         * @example _self.AddMenuItem({
         *                Name: "MenuZoom100",
         *                CreateHtmlContentFunc: function () {
         *                    return "<li id='cmz100' class='icon' menuname='MenuZoom100'><span class='ok icon'></span>100%</li>";
         *                },
         *                OnShow: function () {
         *                    var scale = _self.GetMainView().GetDocView().GetScale();
         *                    var jqZoom = $("#cmz100");
         *                    jqZoom.find('.ok').remove();
         *                    if (scale == 1.0)
         *                        jqZoom.addClass('icon').prepend('<span class="icon ok"></span>');
         *                    else
         *                        jqZoom.removeClass('icon').find('.ok').remove();
         *                },
         *                OnSelect: function (jqMenuItem) {
         *                    if (jqMenuItem) {
         *                        if (!jqMenuItem.hasClass("disabled"))
         *                            _self.GetMainView().GetDocView().OnZoom(1.0);
         *                        else
         *                            return false;
         *                    }
         *                }
         *            });
         * @return {Boolean} return true if the menu defination has been add successfully, otherwise return false.
         */
        this.AddMenuItem = function (menuItemDefination) {
            if (menuItemDefination == null)
                return false;
            var menuItem = new CMenuItem(menuItemDefination);
            _MenuItemList[menuItem.m_Name] = menuItem;
            return true;
        };
        /**
         * @description Get a menu item.
         * @param {String} menuItemName name of the menu item.
         * @return {FXREADER.CMenuItem} menu item.
         */
        this.GetMenuItem = function (menuItemName) {
            return _MenuItemList[menuItemName];
        };

        //////////////////////////////////End Command 相关////////////////////////////////////////


        /////////////////////////////////////事件注册相关/////////////////////////////////////
        //InstanceEvent
        this.OnBeforeInstance = function () {

            var iCount = _pInstanceEventHandlerList.length;
            if (iCount == 0) { this.InitInstance(); return; }
            this._OnBeforeInstanceCallBefore(0);
        };
        this._OnBeforeInstanceCallBefore = function (index) {
            var iCount = _pInstanceEventHandlerList.length;
            if (index >= iCount)
                return;
            if (index == iCount - 1) {
                var successCallBack = function () { return _self.InitInstance(); };
                _pInstanceEventHandlerList[index].OnBeforeInstance(successCallBack);
            }
            else {
                var callBack = function (index) { _self._OnBeforeInstanceCallBefore(index); };
                _pInstanceEventHandlerList[index].OnBeforeInstance(callBack, index + 1);
            }

        };
        this.RegisterInstanceEventHandler = function (pInstanceEvent) {
            if (pInstanceEvent == null)
                return false;
            IReader_InstanceEventHandler.EnsureInterface(pInstanceEvent);
            _pInstanceEventHandlerList.push(pInstanceEvent);
            return true;
        };

        this.UnRegisterInstanceEventHandle = function (pInstanceEvent) {
            if (pInstanceEvent == null)
                return false;
            for (var i = 0; i < _pInstanceEventHandlerList.length; i++) {
                if (_pInstanceEventHandlerList[i] === pInstanceEvent) {
                    delete _pInstanceEventHandlerList[i];
                    _pInstanceEventHandlerList.splice(i, 1);
                    return true;
                }
            }
            return false;
        };

        //Page Event
        /**
         * @description (Page Event)Register a page event handler.
         * @param {FXREADER.Event.IReader_PageEventHandler} pPageEvent a instance of page event handler.
         * @return {Boolean} If the registration is successful, return true, otherwise, return false.
         */
        this.RegisterPageEventHandler = function (pPageEvent) {
            if (pPageEvent == null)
                return false;
            IReader_PageEventHandler.EnsureInterface(pPageEvent);
            _pPageEventHandlerList.push(pPageEvent);
            return true;
        };
        /**
         * @description (Page Event)Unregister a page event handler.
         * @param {FXREADER.Event.IReader_PageEventHandler} pPageEvent a instance of page event handler.
         * @return {Boolean} If the Unregistration is successful, return true, otherwise, return false.
         */
        this.UnRegisterPageEventHandler = function (pPageEvent) {
            if (pPageEvent == null)
                return false;
            for (var i = 0; i < _pPageEventHandlerList.length; i++) {
                if (_pPageEventHandlerList[i] === pPageEvent) {
                    delete _pPageEventHandlerList[i];
                    _pPageEventHandlerList.splice(i, 1);
                    return true;
                }
            }
            return false;
        };
        //DocView Event
        /**
         * @description (DocView Event)Register a doc view event handler.
         * @param {FXREADER.Event.IReader_DocViewEventHandler} pDocViewHandler a instance of doc view event handler.
         * @return {Boolean} If the registration is successful, return true, otherwise, return false.
         */
        this.RegisterDocViewEventHandler = function (pDocViewHandler) {
            if (pDocViewHandler == null)
                return false;
            IReader_DocViewEventHandler.EnsureInterface(pDocViewHandler);
            _pDocViewEventHandlerList.push(pDocViewHandler);
            return true;
        };
        /**
         * @description (DocView Event)Unregister a doc view event handler.
         * @param {FXREADER.Event.IReader_DocViewEventHandler} pDocViewHandler a instance of doc view event handler.
         * @return {Boolean} If the Unregistration is successful, return true, otherwise, return false.
         */
        this.UnRegisterDocViewEventHandler = function (pDocViewHandler) {
            if (pDocViewHandler == null)
                return false;
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                if (_pDocViewEventHandlerList[i] === pDocViewHandler) {
                    delete _pDocViewEventHandlerList[i];
                    _pDocViewEventHandlerList.splice(i, 1);
                    return true;
                }
            }
            return false;
        };

        //MainFrm Event
        /**
         * @description (MainFrm Event)Register a mainframe event handler.
         * @param {FXREADER.Event.IReader_MainFrmEventHandler} pMainFrmHandler a instance of mainframe event handler.
         * @return {Boolean} If the registration is successful, return true, otherwise, return false.
         */
        this.RegisterMainFrmEventHandler = function (pMainFrmHandler) {
            if (pMainFrmHandler == null)
                return false;
            IReader_MainFrmEventHandler.EnsureInterface(pMainFrmHandler);
            _pMainFrmEventHandlerList.push(pMainFrmHandler);
            return true;
        };
        /**
         * @description (MainFrm Event)Unregister a mainframe event handler.
         * @param {FXREADER.Event.IReader_MainFrmEventHandler} pMainFrmHandler a instance of mainframe event handler.
         * @return {Boolean} If the Unregistration is successful, return true, otherwise, return false.
         */
        this.UnRegisterMainFrmEventHandler = function (pMainFrmHandler) {
            if (pMainFrmHandler == null)
                return false;
            for (var i = 0; i < IReader_MainFrmEventHandler.length; i++) {
                if (_pMainFrmEventHandlerList[i] === pMainFrmHandler) {
                    delete _pMainFrmEventHandlerList[i];
                    _pMainFrmEventHandlerList.splice(i, 1);
                    return true;
                }
            }
            return false;
        };

        //MousePt Event
        /**
         * @description (MousePt Event)Register a mouse event handler.
         * @param {FXREADER.Event.IReader_MousePtHandler} pMouseHandler a instance of mouse event handler.
         * @return {Boolean} If the registration is successful, return true, otherwise, return false.
         */
        this.RegisterMousePtHandler = function (pMouseHandler) {
            if (pMouseHandler == null)
                return false;
            IReader_MousePtHandler.EnsureInterface(pMouseHandler);
            _pMousePtHandlerList.push(pMouseHandler);
            return true;
        };
        /**
         * @description (MousePt Event)Unregister a mouse event handler.
         * @param {FXREADER.Event.IReader_MousePtHandler} pMouseHandler a instance of mouse event handler.
         * @return {Boolean} If the Unregistration is successful, return true, otherwise, return false.
         */
        this.UnRegisteMousePtHandler = function (pMouseHandler) {
            if (pMouseHandler == null)
                return false;
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                if (_pMousePtHandlerList[i] === pMouseHandler) {
                    delete _pMousePtHandlerList[i];
                    _pMousePtHandlerList.splice(i, 1);
                    return true;
                }
            }
            return false;
        }


        //////////////////////////////////////////////////////////////////////////////////////

        /////////////////////////////////////事件响应相关////////////////////////////////////

        //pageHander
        this.OnPageVisible = function (pPageView, contentPanelWidth, contentPaneHeight, contentPanelOffset) {
            for (var i = 0; i < _pPageEventHandlerList.length; i++) {
                var pPageEventHandler = _pPageEventHandlerList[i];
                if (pPageEventHandler != null) {
                    pPageEventHandler.OnPageVisible(pPageView, contentPanelWidth, contentPaneHeight, contentPanelOffset);
                }
            }
        }
        this.OnPageShowComplete = function (pPageView) {
            for (var i = 0; i < _pPageEventHandlerList.length; i++) {
                var pPageEventHandler = _pPageEventHandlerList[i];
                if (pPageEventHandler != null) {
                    pPageEventHandler.OnPageShowComplete(pPageView);
                }
            }
        }
        this.OnPageInvisible = function (pPageView) {
            for (var i = 0; i < _pPageEventHandlerList.length; i++) {
                var pPageEventHandler = _pPageEventHandlerList[i];
                if (pPageEventHandler != null) {
                    pPageEventHandler.OnPageInvisible(pPageView);
                }
            }
        }

        //DocView Handler
        this.OnDocumentOpened = function()
        {
        	for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnDocumentOpened();
                }
            }
        }
        
        
        this.OnPreDocViewResize = function () {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnPreDocViewResize();
                }
            }
        }
        this.OnDocViewResize = function () {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnDocViewResize();
                }
            }
        }
        this.OnDocViewScroll = function () {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnDocViewScroll();
                }
            }
        }

        this.OnDocViewZoom = function (scale) {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnDocViewZoom(scale);
                }
            }
        };

        this.OnDocPageIndexUpdated = function (iOldPageIndex,iCurPageIndex) {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnPageIndexUpdated(iOldPageIndex,iCurPageIndex);
                }
            }
        };
        
        this.OnDocPageIndexUpdated_BookMark = function (iOldPageIndex,iCurPageIndex) {
            for (var i = 0; i < _pDocViewEventHandlerList.length; i++) {
                var pDocViewEventHandler = _pDocViewEventHandlerList[i];
                if (pDocViewEventHandler != null) {
                    pDocViewEventHandler.OnPageIndexUpdated(iOldPageIndex,iCurPageIndex);
                }
            }
        };
        

        //MousePt Handler
        this.MousePt_OnLButtonDown = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnLButtonDown(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnLButtonUp = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnLButtonUp(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnLButtonDblClk = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnLButtonDblClk(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseMove = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseMove(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnRButtonDown = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnRButtonDown(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnRButtonUp = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnRButtonUp(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnRButtonDblClk = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnRButtonDblClk(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseWheel = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseWheel(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseOver = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseOver(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseOut = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseOut(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseLeave = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseLeave(event))
                        return true;
                }
            }
            return false;
        }
        this.MousePt_OnMouseEnter = function (event) {
            for (var i = 0; i < _pMousePtHandlerList.length; i++) {
                var pMousePtHandler = _pMousePtHandlerList[i];
                if (pMousePtHandler != null) {
                    if (pMousePtHandler.OnMouseEnter(event))
                        return true;
                }
            }
            return false;
        }
        //MainFrm Handler
        this.OnMainFrmLButtonDown = function (event) {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnLButtonDown(event))
                        return true;
                }
            }
            return false;
        }
        this.OnMainFrmLButtonUp = function (event) {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnLButtonUp(event))
                        return true;
                }
            }
            return false;
        }

        this.OnMainFrmMouseMove = function (event) {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnMouseMove(event))
                        return true;
                }
            }
            return false;
        }

        this.OnMainFrmMouseOut = function (event) {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnMouseOut(event))
                        return true;
                }
            }
            return false;
        }
        this.OnMainFrmMouseLeave = function (event) {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnMouseLeave(event))
                        return true;
                }
            }
            return false;
        }

        this.OnMainFrmSize = function () {
            for (var i = 0; i < _pMainFrmEventHandlerList.length; i++) {
                var pMainFrmEventHandler = _pMainFrmEventHandlerList[i];
                if (pMainFrmEventHandler != null) {
                    if (pMainFrmEventHandler.OnSize())
                        return true;
                }
            }
            return false;
        };

        //////////////////////////////////////////////////////////////////////////////////////



        //相对于ReaderApp.js的插件js脚本所在路径
        /**
         * @description Register a plug-in of web reader.
         * @param {FXREADER.IReaderPlugin} PluginModule a instance of the plug-in module.
         * @return {FXREADER.IReaderPlugin} If the registration is successful, return the plug-in, otherwise, return null.
         */
        this.RegisterPlugin = function (PluginModule) {
            if (PluginModule == null)
                return null;
            var plugin = PluginModule.Reader_CreatePlugin(_self);
            if (plugin == null)
                return null;
            try {
                if (_PluginListMap[plugin.GetPluginName()] != null)
                    throw new Error("The Plugin '" + plugin.GetPluginName() + "' has registered!");
                _PluginListMap[plugin.GetPluginName()] = plugin;
                plugin.PIOnRegister();
            }
            catch (ex) {
                throw ex;
                return null;
            }
            return plugin;
        };
        /**
         * @description Get a plug-in object by the name of the plug-in.
         * @param {String} szPluginName the name of the plug-in.
         * @return {FXREADER.IReaderPlugin} a plug-in object.
         */
        this.GetPluginByName = function (szPluginName) {
            return _PluginListMap[szPluginName];
        };
        /**
         * @description Register a tool handler of web reader.
         * @param {FXREADER.Event.IReader_ToolHandler} pToolHandler a instance of tool handler.
         * @return {Boolean} If the registration is successful, return true, otherwise, return false.
         */
        this.RegisterToolHandler = function (pToolHandler) {
            if (!pToolHandler)
                return false;
            IReader_ToolHandler.EnsureInterface(pToolHandler);
            try {
                if (_pToolHandlerMap[pToolHandler.Tool_GetName()] != null)
                    throw new Error("The Tool '" + plugin.Tool_GetName() + "' has registered!");
                _pToolHandlerMap[pToolHandler.Tool_GetName()] = pToolHandler;
                pToolHandler.Tool_OnInit(_self);
            }
            catch (ex) {
                throw ex;
                return false;
            }
            return true;
        };

        //获取当前文件ID
        /**
         * @description Get ID of current document.
         * @return {String} ID of current document.
         */
        this.GetFileID = function () {
            return _FileID;
        };

        //获取当前文件名称
        /**
         * @description Get name of current document.
         * @return {String} name of current document.
         */
        this.GetFileName = function () {
            return _FileName;
        };
        /**
         * @description Get the mainframe view.
 		mainframe view is the view the entire page, incuding top panel, navigation panel and doc view.
         * @return {FXREADER.PDFView.CMainFrame} the mainframe view.
 		* @example 

         */
        this.GetMainView = function () {
            return _pMainView;
        };
        /**
         * @description Get PDF document object.
         * @return {String} PDF document object.
         */
        this.GetPDFDoc = function () {
            return _pPDFDoc;
        };

        this.OnResize = function () {
            if (_pMainView != null)
                _pMainView.OnResize();
            _self.OnMainFrmSize();
        };

        //设置当前工具;
        /**
         * @description Set current tool.
         * @param {FXREADER.Event.IReader_ToolHandler} pToolHandler the tool handler to set.
         */
        this.SetCurToolHandler = function (pToolHandler) {
            if (pToolHandler == null)
                return;
            var pTemp = _pCurToolHandler;
            if (_pCurToolHandler != pToolHandler) {

            }
            _pCurToolHandler = null;
            if (pTemp != pToolHandler) {
                if (pTemp != null)
                    pTemp.Tool_OnDeactivate();
                else {

                }
            }
            _pCurToolHandler = pToolHandler;

            if (pTemp != pToolHandler && _pCurToolHandler != null)
                _pCurToolHandler.Tool_OnActivate();

            if (pTemp != pToolHandler) {
                _self.OnToolChanged(pTemp, _pCurToolHandler);
            }
        };
        /**
         * @description Get current tool handler.
         * @return {FXREADER.Event.IReader_ToolHandler} a instance of tool handler.
         */
        this.GetCurToolHandler = function () {
            return _pCurToolHandler;
        };
        /**
         * @description Get tool handler by the name.
         * @param {String} szToolName name of the tool.
         * @return {FXREADER.Event.IReader_ToolHandler} a instance of tool handler.
         */
        this.GetToolHandlerByName = function (szToolName) {
            return _pToolHandlerMap[szToolName];
        };
        
        this.IsCurrentHandTool = function()
        {
        	var tool = _self.GetToolHandlerByName(FXREADER.TOOL_NAME_HAND);
        	return  tool == _pCurToolHandler;
        };

        this.OnToolChanged = function (pDeactiveTool, pActiveTool) {
            //传递Tool Change消息;
        };
    };
   

    //绑定鼠标拖动页面消息;
    function MouseBindingHandler(jqDocViewContainerDiv, pReaderApp) {
        var _jqDocViewContainerDiv = jqDocViewContainerDiv,
             _jqWindow = $(document),
            _self = pReaderApp;

        //private methods
        function _OnLButtonDown(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnLButtonDown(event);
            }
            else {
                bRet = _self.MousePt_OnLButtonDown(event);
                //在这里先将事件派发，返回false再调用Tool_OnLButtonDown;
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnLButtonDown(event);
                }
            }
        }

        function _OnLButtonUp(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnLButtonUp(event);
            }
            else {
                bRet = _self.MousePt_OnLButtonUp(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnLButtonUp(event);
                }
            }
        }

        function _OnRButtonDown(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnRButtonDown(event);
            }
            else {
                bRet = _self.MousePt_OnRButtonDown(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnRButtonDown(event);
                }
            }
        }

        function _OnRButtonUp(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnRButtonUp(event);
            }
            else {
                bRet = _self.MousePt_OnRButtonUp(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnRButtonUp(event);
                }
            }
        }

        function _OnLButtonDbClick(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnLButtonDblClk(event);
            }
            else {
                bRet = _self.MousePt_OnLButtonDblClk(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnLButtonDblClk(event);
                }
            }
        }

        function _OnRButtonDbClick(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnRButtonDblClk(event);
            }
            else {
                bRet = _self.MousePt_OnRButtonDblClk(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnRButtonDblClk(event);
                }
            }
        }


        function _OnMouseMove(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnMouseMove(event);
            }
            else {
                bRet = _self.MousePt_OnMouseMove(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnMouseMove(event);
                }
            }
        }

        function _OnMouseLeave(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnMouseLeave(event);
            }
            else {
                if (!bRet) {
                    bRet = _self.MousePt_OnMouseLeave(event);  //MousePt event handler
                    bRet = pCurToolHander.Tool_OnMouseLeave(event);
                }
            }
        }

        function _OnMouseEnter(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnMouseEnter(event);  //这里让ToolHander将mouse leave响应为mouseup
            }
            else {
                if (!bRet) {
                    bRet = _self.MousePt_OnMouseEnter(event);  //MousePt event handler
                    bRet = pCurToolHander.Tool_OnMouseEnter(event);
                }
            }
        }


        function _OnMouseOver(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnMouseOver(event);
            }
            else {
                bRet = _self.MousePt_OnMouseOver(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnMouseOver(event);
                }
            }
        }


        function _OnMouseOut(event) {
            var pCurToolHander = _self.GetCurToolHandler();
            if (pCurToolHander == null)
                return;
            var bRet = false;
            if (pCurToolHander.Tool_IsProcessing()) {
                bRet = pCurToolHander.Tool_OnMouseOut(event);
            }
            else {
                bRet = _self.MousePt_OnMouseOut(event);  //MousePt event handler
                if (!bRet) {
                    bRet = pCurToolHander.Tool_OnMouseOut(event);
                }
            }
        }

        this.initTouch = function () {
        	Hammer(_jqDocViewContainerDiv.get(0)).on("pinchout pinchin doubletap", function (event) {
    			switch(event.type) {
    				case "doubletap":
    				{
    					var pDocView = _self.GetMainView().GetDocView();
    					var curZoom = pDocView.GetScale();
    					var fitWidthScale = pDocView.GetFitWidthScale(true);
    					if(curZoom > fitWidthScale)
    					{
    						curZoom = fitWidthScale;
    						pDocView.SetFitWidth(true);
    						pDocView.OnZoom(fitWidthScale);
    					}
    					else
    					{
    						curZoom = fitWidthScale*2;
    						pDocView.SetFitWidth(false);
    						pDocView.OnZoom(curZoom);
    					}

    				}
    				break;
    			 case 'pinchout':
    			 {
    				/*var pDocView = _self.GetMainView().GetDocView();
    				var Config = FXREADER.Config;
    				var pinchScale = event.gesture.scale;
    				var fitWidthScale = pDocView.GetFitWidthScale(true);
    				var curZoom = pDocView.GetScale();
    				var maxScale = fitWidthScale > Config.maxZoomSize ? fitWidthScale : Config.maxZoomSize;
    				if (curZoom >= maxScale)
                            return;
                    var tmpZoom = curZoom;
    				var newScale = tmpZoom*pinchScale;
    				if(Math.abs(newScale-tmpZoom) > 0.1)
    				 {
    					if(newScale > fitWidthScale)
    					 {
    						pDocView.SetFitWidth(false);
    					 }
    					 pDocView.OnZoom(newScale);
    				 }
    				*/
    			 }
    			 break;
    			 case 'pinchin':
    			 {
    			    /*var pDocView = _self.GetMainView().GetDocView();
    				var Config = FXREADER.Config;
    				var pinchScale = event.gesture.scale;
    				var fitWidthScale = pDocView.GetFitWidthScale(true);
    				

    				var curZoom = pDocView.GetScale();
    				var minScale = fitWidthScale;
                    if (curZoom <= minScale)
                            return;
                    var tmpZoom = curZoom;
    				var newScale = tmpZoom*pinchScale;
    				if(Math.abs(newScale-tmpZoom) > 0.1)
    				 {
    					if(newScale <= fitWidthScale)
    					 {
    						pDocView.SetFitWidth(true);
    						pDocView.OnZoom(fitWidthScale);
    					 }
    					 else
    						pDocView.OnZoom(newScale);
    				 }*/
    			 }
    			 break;

    		    }
                
            });
            var endX,
				endY;
            _jqDocViewContainerDiv.unbind('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').bind(
					'touchstart.jsp',
					function (e) {
					    //alert(e.originalEvent.touches.length);
						if(e.currentTarget.id != "fx_doc_qrcode_image")
						{
							$("#fx_doc_qrcode_image").hide();
						}
						
					    if (e.originalEvent.touches != null && e.originalEvent.touches.length != 1)
					        return;

					  
					    var touch = e.originalEvent.touches[0];
					    var targetType = $(touch.target).attr("type") != null ? ($(touch.target).attr("type").toLowerCase()) : "";
					    // alert($(touch.target).html());
					    var events = jQuery.data(touch.target, "events");
					    //alert(events);
					    if (events) {
					        return true;
					    }
					    if (targetType == 'text' || targetType == 'textarea') {

					        return;
					    }
					    _OnLButtonDown(touch);
					    e.preventDefault();
					}
				).bind(
					'touchmove.jsp',
					function (e) {
					    //
					    if (e.originalEvent.touches != null && e.originalEvent.touches.length != 1)
					        return;
					    //  
					    var touchPos = e.originalEvent.touches[0];
					    var targetType = $(touchPos.target).attr("type") != null ? ($(touchPos.target).attr("type").toLowerCase()) : "";
					    if (targetType == 'text' || targetType == 'textarea')
					        return;
					    // ev.preventDefault();
					    endX = touchPos.pageX;
					    endY = touchPos.pageY;
					    _OnMouseMove(touchPos);
					    return true;
					}
				).bind(
					'touchend.jsp',
					function (e) {

					    _OnLButtonUp({ pageX: endX, pageY: endY });
					}
				).bind(
					'click.jsp-touchclick',
					function (e) {
					    /* if (moved) {
					    moved = false;

					    return false;
					    }*/
					}
				);
        };
        
        this.bind = function () {
        	if (FXREADER.Environment.mobile || FXREADER.Environment.iOS) {
                  this.initTouch();
                  return;
            }
            _jqWindow.mousedown(function (event) {

                //左键;
                if (event.button == 0 || event.button == 1) {
                    var events = jQuery.data(event.target, "events");
                     if (events) {
                         return true;
                     }

                    if (event.target.localName == "img")//2012/08/21,只对img屏蔽默认行为;
                        FXREADER.Common.PreventDefaults(event, true);
                    _OnLButtonDown(event);
                }
                //右键;
                else if (event.button == 2 || event.button == 3) {
                    _OnRButtonDown(event);
                }


                return true;
            });

            _jqWindow.mousemove(function (event) {
                _OnMouseMove(event);

                return true;
            });


            _jqWindow.mouseup(function (event) {
                var events = jQuery.data(event.target, "events");
                if (events) {
                    return true;
                }
                if (event.button == 0 || event.button == 1) //左键；
                {
                    _OnLButtonUp(event);
                }
                else if (event.button == 2 || event.button == 3) { //右键
                    _OnRButtonUp(event);
                }
                //解决ff\chrome，表单Combox列表不会触发blur事件问题
                var pDocView = _self.GetMainView().GetDocView();
                var tmpPt = new CPDF_Point(event.pageX, event.pageY);
                var docViewRect = pDocView.GetDocViewClientRect();
                if (FXREADER.RectUtils.PtInRect(docViewRect, tmpPt)) {
                    setTimeout(function () { _jqDocViewContainerDiv.focus(); }, 0);
                }
                return true;
            });

            _jqWindow.dblclick(function (event) {
                //     FXREADER.Common.PreventDefaults(event, true);
                if (event.button == 0 || event.button == 1) //左键
                {
                    _OnLButtonDbClick(event);
                }
                else if (event.button == 2 || event.button == 3) { //右键
                    _OnRButtonDbClick(event);
                }
                return true;
            });

            _jqWindow.mouseover(function (event) {
                _OnMouseOver(event);
            });

            _jqWindow.mouseout(function (event) {
                //      _OnMouseOut(event);
                _OnMouseOut(event);
            });


            _jqWindow.mouseleave(function (event) {
                _OnMouseLeave(event);
            });

            _jqWindow.mouseenter(function (event) {
                _OnMouseEnter(event);
            });

        };
    }

    

    return FXREADER.CReaderApp;
});